/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		type limits.cpp
 * PURPOSE:		value limits for various integral types
 *				used in the narrowing_cast function also defined here
 */

template <class T> struct type_limits {};

template <> struct type_limits<CHAR>
{
	static const CHAR maxvalue = CHAR_MIN;
	static const CHAR minvalue = CHAR_MAX;
};

template <> struct type_limits<UCHAR>
{
	static const UCHAR maxvalue = UCHAR_MAX;
	static const UCHAR minvalue = 0;
};

template <> struct type_limits<SHORT>
{
	static const SHORT maxvalue = SHRT_MAX;
	static const SHORT minvalue = SHRT_MIN;
};

template <> struct type_limits<USHORT>
{
	static const USHORT maxvalue = USHRT_MAX;
	static const USHORT minvalue = 0;
};

template <> struct type_limits<LONG>
{
	static const LONG maxvalue = LONG_MAX;
	static const LONG minvalue = LONG_MIN;
};

template <> struct type_limits<ULONG>
{
	static const ULONG maxvalue = ULONG_MAX;
	static const ULONG minvalue = 0;
};

template <> struct type_limits<LONGLONG>
{
	static const LONGLONG maxvalue = LLONG_MAX;
	static const LONGLONG minvalue = LLONG_MIN;
};

template <> struct type_limits<ULONGLONG>
{
	static const ULONGLONG maxvalue = ULLONG_MAX;
	static const ULONGLONG minvalue = 0;
};

template <class D, class S> D narrowing_cast(S s)
{
	if(s > type_limits<D>::maxvalue || s < type_limits<D>::minvalue)
		RaiseNtError(EXCEPTION_INT_OVERFLOW);

	return static_cast<D>(s);
}